
using System;
using System.Collections.Generic;
using System.Speech.Recognition;
using TencentCloud.Asr.V20190614;
using TencentCloud.Common.Profile;
using TencentCloud.Common;
using System.Text.Json;
using TencentCloud.Asr.V20190614.Models;
using System.IO;
using project1113.Wrold;
using project1113.SomeTools;
using System.Windows;
using project1113.iniParser;
using project1113.observer;

namespace project1113.SpeechRecoginzer
{///<切换语音模式>
///  WorldModel.CurrentWorld.SpeechReco.Mode = _mode.mode_Local;->切换至本地模式
/// </summary>
    public class SpeechRecoginzer
    {
        //配置参数
        string? _SecretId = null;
        string? _SecretKey = null;
        string? _CallWord = null;
        string? _PrefixWord = null;
        string? _BusyWord = null;
        private  string _last_message;//远程的回答
        private  string _out_message;
        private SpeechRecognizeMode _mode;
        const int STENCE_PER_INTERVAL = 4;
        const int VOLUME_GATE = 8;
        private  string _last_intent;
        private  string _out_intent;
        private bool _last_isoverchat = false;
        private  bool _out_isoverchat = false;
        private  bool isStar = false;
        public List<SlotInfo> slotInfoList { get; private set; }
        //private  List<SlotInfo> _out_slotInfoList;
        public  readonly int RecorderTime = 3000;
        private  bool _isCalled = false;
        private bool _Turnoff = false;
        private TBP myBot;//对话机器人
        private Credential cred;
        private ClientProfile clientProfile;
        // 实例化要请求产品的client对象,clientProfile是可选的
        private AsrClient client;
        #region//SpeechReo
        public SpeechRecognizeMode Mode
        {
            get
            {
                return _mode;
            }
            set
            {
                //执行切换
                if (_mode != value)
                {
                    Stop();
                    switch (value)
                    {
                        case SpeechRecognizeMode.mode_Init:
                            //StartMode_Exigence();
                            break;
                        case SpeechRecognizeMode.mode_Local:

                            StartMode_Local();
                            break;
                        case SpeechRecognizeMode.mode_Remote:
                            StartMode_Remote();
                            break;
                        case SpeechRecognizeMode.mode_Exigence:
                            
                            break;
                    }
                    _mode = value;

                }

            }

        }
        public SpeechRecoginzer()
        {
            string iniFilePath = @"conf\SpeechRecongizeConf.ini";
            var iniParser = new IniParser(iniFilePath, new Observe_err());

            try
            {
                _SecretId = iniParser.GetSetting("_SecretId") ?? throw new Exception("SpeechRecongize缺少参数: _SecretId");
                _SecretKey = iniParser.GetSetting("_SecretKey") ?? throw new Exception("SpeechRecongize缺少参数: _SecretKey");
                _CallWord = iniParser.GetSetting("WakeupWords") ?? (_CallWord = "小智你在吗");//有默认值 默认值为“小智，你在吗”
                _PrefixWord = iniParser.GetSetting("PrefixWords") ?? (_PrefixWord = "开始录音");
                _BusyWord = iniParser.GetSetting("BusyWords") ?? (_BusyWord = "小智正在忙");
            }
            catch (Exception e)
            {
                //应该做一下观察器，我就算了,懒得麻烦--zlj
                MessageBox.Show(e.Message);
                StaticLogWrite.Logger.Log(LogLevel.Error, e.Message);
            }

            Init_Local();
            System.Threading.Tasks.Task.Run(Init_Remote);

        }//语音的构造函数     
        public void Update()
        {
            _out_message = _last_message;
            _last_message = string.Empty;
            _out_intent = _last_intent;
            _last_intent = string.Empty;
            _out_isoverchat = _last_isoverchat;
            _last_isoverchat = false;
            //_out_slotInfoList = _last_slotInfoList;
            //if (_last_slotInfoList != null)
            //{
            //    _last_slotInfoList.Clear();
            //}

        }//更新         
        private void Stop()
        {
            try
            {
                recognitionEngine.RecognizeAsyncStop();
            }
            catch (Exception)
            {

            }
            try
            {
                isStar = false;
            }
            catch (Exception)
            {

            }
        }
        #endregion

        #region //Local

        SpeechRecognitionEngine recognitionEngine = new SpeechRecognitionEngine();//给本地用的事件
        //--Interface-------------------------------------------------------------------------------------------------
        public  bool local_IsCalled()
        {
            bool _isCalled = this._isCalled;
            this._isCalled = false;//待议，查过一次上一次唤醒的记录就会被清,这个函数会在状态机按周期查询
            return _isCalled;
        }
        public bool local_Turnoff()
        {
            bool _Turnoff = this._Turnoff;
            this._Turnoff = false;//待议，查过一次上一次唤醒的记录就会被清,这个函数会在状态机按周期查询
            return _Turnoff;
        }
        //---------------------------------------------------------------------------------------------------
        private void StartMode_Local()
        {
            recognitionEngine.RecognizeAsync(RecognizeMode.Multiple);//开启本地
            //recognitionEngine.RecognizeAsync(RecognizeMode.Multiple);//开启本地

        }
        private void Init_Local()
        {
            Choices wakeUpWords;
            // 创建一个自定义语法，包括唤醒词
            wakeUpWords = new Choices(new string[] { _CallWord, "关机" });
            GrammarBuilder grammarBuilder = new GrammarBuilder(wakeUpWords);

            Grammar grammar = new Grammar(grammarBuilder);

            recognitionEngine.LoadGrammar(grammar);

            // 注册事件处理程序以处理语音识别结果
            recognitionEngine.SpeechRecognized += (s, e_e) =>
            {
                if (e_e.Result != null)
                {
                    if(e_e.Result.Text== _CallWord)
                    //唤醒成功
                    // WorldModel.CurrentWorld.TTS.Speak("切换到本地模式");
                    //project1113.Wrold.WorldModel.CurrentWorld.TTS.Speak("切换到本地模式");
                    _isCalled = true;
                    // Debug.WriteLine("唤醒");
                    // 在这里可以执行你的操作，例如打开应用程序或触发其他操作。
                    else if(e_e.Result.Text=="关机")
                    {
                        _Turnoff=true;
                    }
                }
                else
                {

                }
            };
            recognitionEngine.SetInputToDefaultAudioDevice();
        }

        #endregion

        #region //Remote
        //--Interface-------------------------------------------------------------------------------------------------
        public  string GetMessage()
        {
            return _out_message;
        }//外部获取语音的接口
        public  string GetIntent()
        {
            return _out_intent;
        }
        //public  List<SlotInfo> SlotInfo()
        //{

        //    return _out_slotInfoList;
        //}
        public bool Remote_IsOverChat()
        {
          
            return _out_isoverchat;
        }
        //---------------------------------------------------------------------------------------------------
        private void Init_Remote()
        {
            myBot = new TBP();
            cred = new Credential
            {
                SecretId = _SecretId,
                SecretKey = _SecretKey,

                //SecretId = "AKIDUwaIC1jHj15uVt34teHg3E8uTr5EF8tU",
                //SecretKey = "e2GPV1VwC6tUt3y64pXIuOWeiaEj06Rx"
            };
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            clientProfile = new ClientProfile();
            // 实例化要请求产品的client对象,clientProfile是可选的
            client = new AsrClient(cred, "", clientProfile);
            while (true)
            {
                if (isStar)
                {
                    if (_PrefixWord != null)
                    {
                        WorldModel.CurrentWorld.TTS.Speak(_PrefixWord);
                    }
                    string output = Recorder();
                    try
                    {
                        TextProcessRequestJson_for_speech resObj_speech = SpeechRecognate(client, output);
                        if (resObj_speech.Result.Length != 0)
                        {

                            TextProcessRequestJson_for_connection _result = myBot.SendtoBot(resObj_speech.Result);
                            _last_message = _result.ResponseText;
                            _last_intent = _result.IntentName;
                            slotInfoList = _result.SlotInfoList;
                            if (!WorldModel.CurrentWorld.Robot.isBusy) 
                            { 
                                WorldModel.CurrentWorld.TTS.Speak(_last_message);
                                
                            }
                            
                            else
                            {
                                if(_last_intent == "hghjg" || _last_intent == "P2p" || _last_intent == "Handover" || _last_intent == "LoseHand")
                                {
                                    _last_message = string.Empty;
                                    _last_intent = string.Empty;
                                    slotInfoList.Clear();
                                    WorldModel.CurrentWorld.TTS.Speak(_BusyWord);
                                }
                                

                                else
                                {
                                    WorldModel.CurrentWorld.TTS.Speak(_last_message);
                                }
                            }
                            
                        }
                        else
                        {
                            _last_isoverchat = true;
                            isStar = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        //TODO 错误处理
                    }


                }

            }
        }
        private void StartMode_Remote()
        {
            isStar = true;

        }
        private static string Recorder()
        {
            //while (TTS.GetTTSisSpeaking())
            //{
            //}
            timerTick shortTimerTick = new timerTick();
            string outputFilePath = "outputFilePath";
            MicrophoneRecorder recorder = new MicrophoneRecorder();
            string output = recorder.StartRecording(outputFilePath);
            shortTimerTick.timerTickerStart(1000); //ms
            while (shortTimerTick.GetTimerCounter() <= STENCE_PER_INTERVAL)
            {

                double currentVolume = recorder.GetMicrophoneVolume();

                if (currentVolume > VOLUME_GATE)
                {
                    shortTimerTick.ResetTimerCounter(); // 重置 timerTick
                }

            }
            shortTimerTick.timerTickerStop();
            recorder.StopRecording();
            return output;
        }
        private static TextProcessRequestJson_for_speech SpeechRecognate(AsrClient client, string output)
        {
            SentenceRecognitionRequest req = new SentenceRecognitionRequest();
            req.EngSerViceType = "16k_zh-PY";
            req.SourceType = 1;
            req.VoiceFormat = "wav";
            req.Data = Convert.ToBase64String(File.ReadAllBytes($"{output}"));
            req.DataLen = new FileInfo($"{output}").Length;

            // 返回的resp是一个SentenceRecognitionResponse的实例，与请求对象对应
            SentenceRecognitionResponse resp = client.SentenceRecognitionSync(req);
            // 输出json格式的字符串回包
            //Console.WriteLine(AbstractModel.ToJsonString(resp));
            string jsonStr_speech = AbstractModel.ToJsonString(resp);
            var resObj_speech = JsonSerializer.Deserialize<TextProcessRequestJson_for_speech>(jsonStr_speech);
            return resObj_speech;
        }
        #endregion

    }
 
}
